/*
 * @Author: DUST
 * @Date: 2023-06-20 10:19:44
 * @LastEditors: DUST
 * @LastEditTime: 2023-06-25 14:23:29
 * @FilePath: \national-standard-platform-alarm-screen\src\utils\ckThree\utils.js
 * @Description: 
 * undefined
 */
import * as THREE from "three";
/**
 * move2Center 调整模型位置到视角中心
 * @params object 模型对象
 */
export const move2Center = (object) => {
  // 将模型的中心点设置到canvas坐标系的中心点，保证模型显示是居中的
  let box = new THREE.Box3().setFromObject(object); // 获取模型的包围盒
  let mdlen = box.max.x - box.min.x; // 模型长度
  let mdwid = box.max.z - box.min.z; // 模型宽度
  // let mdhei = box.max.y - box.min.y; // 模型高度
  let x1 = box.min.x + mdlen / 2; // 模型中心点坐标X
  // let y1 = box.min.y + mdhei / 2; // 模型中心点坐标Y
  let z1 = box.min.z + mdwid / 2; // 模型中心点坐标Z
  object.position.set(-x1, 0, -z1);
  // let diagonal = Math.sqrt(
  //   Math.pow(Math.sqrt(Math.pow(mdlen, 2) + Math.pow(mdwid, 2)), 2) +
  //     Math.pow(mdhei, 2)
  // ); // 获取模型整体对角线长度,这里获取模型模型对角线的目的是为了保证模型可以完全的展示在视线范围内
  // 假设我们需要的进入视角为45度
  // this.control.object.position.set(
  //   0,
  //   0,
  //   0
  // ); // 设置相机位置，向上偏移，确定可以包裹整个模型
  // this.control.target.set(x1, y1, z1); // 设置相机的视角方向，看向模型的中心点
  // console.log(x1, y1, z1, box.max.x + diagonal / 2,
  //   (diagonal * 2) / Math.tan((Math.PI / 180) * 90) + Math.abs(box.max.y),
  //   box.max.z + diagonal / 2);
  // // this.plane(x1, y1, z1, mdlen, mdwid, mdhei);
  // this.control.update(); // 更新相机
};


/**
 * onMouseClick 模型点击事件监听
 * @params event 点击事件获取的数据
 * @params camera 相机
 * @params group 模型数据
 */
export const onMouseClick = (event, camera, group, domId, isPc, clickCallBack) => {
  //获取raycaster和所有模型相交的数组，其中的元素按照距离排序，越近的越靠前
  let intersects = getIntersects(event, camera, group, domId, isPc);
  // console.log(intersects);
  // console.log(intersects[0].object);

  //获取选中最近的Mesh对象
  //instance坐标是对象，右边是类，判断对象是不是属于这个类的
  if (intersects.length !== 0 && intersects[0].object.type === "Mesh") {
    console.log("选中的Mesh", intersects, intersects[0].object.name);
    // let selectObject = intersects[0].object;
    const point = transPosition(camera, intersects[0].point);
    // console.log(point);
    intersects[0].screenPosition = transPosition(camera, intersects[0].point);
    if (clickCallBack) clickCallBack(intersects[0], "Mesh");
    // spritePoint(group, selectObject);
    // addModal(point);
    //changeMaterial(selectObject)
  } else if (
    intersects.length !== 0 &&
    intersects[0].object.type === "Sprite"
  ) {
    console.log("选中的Sprite", intersects, intersects[0].object.name);
    intersects[0].screenPosition = transPosition(camera, intersects[0].point);
    if (clickCallBack) clickCallBack(intersects[0], "Sprite");
    // let selectObject = intersects[0].object;
    //changeMaterial(selectObject)
  } else {
    console.log("未选中 Mesh!");
  }
};

/**
 * transPosition 三维坐标转屏幕坐标
 * @params camera: 相机
 * @params position: 需要转换的模型世界坐标
 * @return x: 屏幕坐标横坐标, y: 屏幕坐标纵坐标
 */
export const transPosition = (camera, position) => {
  let world_vector = new THREE.Vector3(position.x, position.y, position.z);
  let vector = world_vector.project(camera);
  let halfWidth = window.innerWidth / 2;
  let halfHeight = window.innerHeight / 2;
  return {
    x: Math.round(vector.x * halfWidth + halfWidth),
    y: Math.round(-vector.y * halfHeight + halfHeight),
  };
};

/**
 * getIntersects 匹配点击事件获取的数据与模型数据比对结果
 * @params event 点击事件获取的数据
 * @params camera 相机
 * @params group 模型数据
 * @return intersects 选中的对象
 */
export const getIntersects = (event, camera, group, domId, isPc) => {
  const canvas = document.querySelector(domId);
  // event.preventDefault(); // 阻止默认的点击事件执行, https://developer.mozilla.org/zh-CN/docs/Web/API/Event/preventDefault
  //console.log("event.clientX:" + event.clientX);
  //console.log("event.clientY:" + event.clientY);

  //声明 rayCaster 和 mouse 变量
  let rayCaster = new THREE.Raycaster();
  let mouse = new THREE.Vector2();

  // const offsetHeigght = canvas.offsetHeight - window.innerHeight;

  //通过鼠标点击位置，计算出raycaster所需点的位置，以屏幕为中心点，范围-1到1
  // console.log(window.innerWidth, window.innerHeight, canvas.getBoundingClientRect().left, event.clientX, canvas.getBoundingClientRect().top, event.clientY + offsetHeigght);
  if (isPc) {
    mouse.x =
      ((event.clientX - canvas.getBoundingClientRect().left) /
        canvas.offsetWidth
      ) * 2 - 1;
    mouse.y = -(
      (event.clientY - canvas.getBoundingClientRect().top) /
      canvas.offsetHeight
    ) * 2 + 1; //这里为什么是-号，没有就无法点中
  } else {
    mouse.x = (event.touches[0].pageX / canvas.offsetWidth) * 2 - 1;
    mouse.y = -(event.touches[0].pageY / canvas.offsetHeight) * 2 + 1;
  }

  //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
  rayCaster.setFromCamera(mouse, camera);

  //获取与射线相交的对象数组， 其中的元素按照距离排序，越近的越靠前。
  //+true，是对其后代进行查找，这个在这里必须加，因为模型是由很多部分组成的，后代非常多。
  let intersects = rayCaster.intersectObjects(group ? group.children : [], true);

  //返回选中的对象
  return intersects;
};
/**
 * @description: 添加toolTips提示
 * @param {*} data:需要展示的数据
 */
export const toolTips = (data, position) => {
  removeToolTips();
  const dom = document.createElement("div");
  dom.id = "toolTips";
  dom.className = "toolTips";
  dom.style.position = "absolute";
  dom.style.left = position.x - 60 + "px";
  dom.style.top = position.y - 50 + "px";
  dom.style.zIndex = 4;
  dom.style.color = "#fff";
  dom.innerHTML = `
    <div class='tooltipsText'>${data.name}</div>
    <div class='toolTips_triangle'></div>
  `;
  document.body.appendChild(dom);
}
/**
 * @description: 移除toolTips提示
 */
export const removeToolTips = () => {
  if (document.getElementById("toolTips")) {
    document.body.removeChild(document.getElementById("toolTips"));
  }
}

/**
 * diffusionCylinder 圆柱扩散波纹
 * @params point: 中心坐标点
 */
export const diffusionCylinder = (point) => {
  let cylinderMesh;
  //创建圆柱
  let geometry = new THREE.CylinderGeometry(3, 3, 6, 64);

  //加载纹理
  let texture = new THREE.TextureLoader().load("static/assets/texture.png");
  texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //每个都重复
  texture.repeat.set(1, 1);
  texture.needsUpdate = true;

  let materials = [
    //圆柱侧面材质，使用纹理贴图
    new THREE.MeshBasicMaterial({
      map: texture,
      side: THREE.DoubleSide,
      transparent: true,
    }),
    //圆柱顶材质
    new THREE.MeshBasicMaterial({
      transparent: true,
      opacity: 0,
      side: THREE.DoubleSide,
    }),
    //圆柱底材质
    new THREE.MeshBasicMaterial({
      transparent: true,
      opacity: 0.5,
      side: THREE.DoubleSide,
    }),
  ];
  cylinderMesh = new THREE.Mesh(geometry, materials);
  cylinderMesh.position.set(point.x, point.y, point.z);

  // 命名
  cylinderMesh.name = "cylinderMesh_" + parseInt(Math.random() * Date.now())

  return cylinderMesh;
  // initPlane(scene, point)
};

// 添加定点锥
export const createTriangularPyramid = (point, color, size = 1) => {
  console.log(size);
  const geometry = new THREE.CylinderGeometry(0, 1 * size, 2 * size, 4, 1);
  const material = new THREE.MeshPhongMaterial({
    color: color,
    flatShading: true
  });
  const mesh = new THREE.Mesh(geometry, material);
  mesh.position.set(point.x, point.y, point.z)
  mesh.rotateZ(Math.PI)
  // 命名
  mesh.name = "triangularPramid_" + parseInt(Math.random() * Date.now())

  return mesh;
}
// 添加文字
export const addText = (point, textContent = "起点") => {
  console.log(new FontLoader())
  new FontLoader().load(
    "/img/STKaiti_Regular.json", //引用上个链接json
    (font) => {
      console.log(font);
      const geometry = new TextGeometry(textContent, {
        font,
        size: 50,
        height: 2,
        curveSegments: 20,
        bevelSegments: 20,
        bevelThickness: 30,
        bevelSize: 1.5,
        bevelEnabled: true
      });
      const material = new THREE.MeshMatcapMaterial({
        color: 0x58ACFA
      });
      const text = new THREE.Mesh(geometry, material);
      text.position.set(point.x, 50, point.z)
      this.textGroup.add(text);
    }
  );
  console.log("文字：", this.textGroup)
}
/**
 * @description: 加载材质
 * @return texture：加载完成的材质对象
 */
export const loadTexture = (imgUrl = "/static/assets/tubeMesh.png", options = {
  repeat: {
    x: 50,
    y: 2,
  },
  offset:{
    y: 0.5
  }
}) => {
  // 加载流动材质
  let tLoader = new THREE.TextureLoader();
  const texture = tLoader.load(imgUrl);
  
  // 设置阵列模式为 RepeatWrapping
  texture.wrapS = THREE.RepeatWrapping
  texture.wrapT = THREE.RepeatWrapping
  texture.repeat.x = options.repeat.x || 50;
  texture.repeat.y = options.repeat.y || 2;
  texture.offset.y = options.offset.y || 0.5;

  return texture;
}
/**
 * @description: 生成管道线路
 * @return tube: 管道线路对象
 */
export const addTubeLine = (lineData, texture, lineOptions = {
  segments: 100, //路径分段数
  radius: 1, //管道半径
  radialSegments: 16, // 管道截面的分段数
  closed: false, // 管道路径是否闭合  
}) => {
  // 处理线路数据生成管道路径
  const v3List = [];
  lineData.forEach(p => {
    v3List.push(new THREE.Vector3(p.x, p.y, p.z))
  });
  let curve = new THREE.CatmullRomCurve3(v3List, false);


  let material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: false,
    // opacity: 0.8,
  });
  let tubeGeometry = new THREE.TubeGeometry(curve, lineOptions.segments || 100, lineOptions.radius || 1, lineOptions.radialSegments || 16, lineOptions.closed || false);
  let tube = new THREE.Mesh(tubeGeometry, material);

  //3、创建一个半透明管道
  // let tubeGeometry2 = new THREE.TubeGeometry(curve, 100, 2, 16, false);
  // let tubeMaterial2 = new THREE.MeshPhongMaterial({
  //   color: 0xaaaaaa,
  //   transparent: true,
  //   opacity: 0.5,
  // });
  // let tube2 = new THREE.Mesh(tubeGeometry2, tubeMaterial2);
  return tube;
}